% !Mode:: "TeX:UTF-8"

\section{项目设计与实现}

\subsection{硬件设计}

\subsubsection{系统总体架构}
系统采用模块化设计，以STM32F103C8T6微控制器为核心，通过外围电路实现人体红外感应、蓝牙、温湿度感应、电机驱动、电源管理等关键功能。系统架构如图\ref{fig:enter-label}所示，包含主控制器模块、红外接收模块、电机驱动模块、电源模块和用户指示模块。
\begin{figure}[h!]
    \centering
    \includegraphics[width=0.5\linewidth]{608458ca4a6106f6c13dda768fddcd23.png}
    \caption{系统架构图}
    \label{fig:enter-label}
\end{figure}
\subsubsection{主控制器模块}
选用STM32F103C8T6微控制器作为主控芯片，主要特性包括：
- 72MHz Cortex-M3内核
- 64KB Flash, 20KB SRAM
- 3个通用定时器（TIM2/TIM3/TIM4）
- 丰富的GPIO接口
- 12位ADC转换器

\subsubsection{人体红外感应模块}
HC-SR501，主要特性：
\begin{itemize}
    \item 工作电压：DC 4.5~20V
    \item 静态电流：<50uA
    \item 电平输出：高3.3V/低0V
    \item 触发方式：L不可重复触发/H重复触发(默认）
    \item 封锁时间：2.5s(默认)可制作范围零点几秒到几十秒
    \item 工作温度：-15到70℃
\end{itemize}

\subsubsection{电机驱动模块}
TB6612FNG ，主要特性：
\begin{itemize}
    \item 驱动电压：VM输入(4.5-10V ）
    \item 逻辑电平：VCC输入(2.7-5.5V ）
    \item 工作电流：1.2A 
    \item 峰值电流：3.2A  
\end{itemize}
通过调节PWM占空比实现三档调速（低：30\%、中：60\%、高：90\%）
\subsubsection{蓝牙模块}
BT04-A ，主要特性：
\begin{itemize}
    \item 使用电压 ：3.3\~5V 
    \item 蓝牙模式 ：从模式 
    \item 最大距离 ：10M 
    \item 配对码 ：1234 
    \item 串口参数 ：9600，8，1，0 
    \item 工作频段 ：2.4GHz ISM频段  
\end{itemize} 
\subsubsection{温湿度传感器}
DHT11，主要特征：
\begin{itemize}
    \item 供电电压：DC 3.3-5.5V
    \item 工作温度范围：-20℃～+60℃
    \item 湿度量程范围：5%RH～95%RH
    \item 温度精度：±2℃
    \item 湿度精度：±5%RH
    \item 重复性：温度：±1℃，湿度：±1%RH
    \item 迟滞：温度：±0.3℃，湿度：±0.3%RH
\end{itemize} 
\subsubsection{OLED显示屏}
OLED，主要特征：
\begin{itemize}
    \item 尺寸：0.96英寸
    \item 工作电压：DC 3~5V
    \item 分辨率：128×64像素
    \item 驱动芯片：SSD1306
    \item 管脚数量：4针
    \item 通信接口：IIC（I²C）
    \item 工作温度范围：-20℃～70℃
\end{itemize} 
\subsubsection{用户指示模块}
- LED状态指示：档位，风速，温度，倒计时等
- 蜂鸣器提示：用于开机、按键反馈等

\subsection{软件设计}
\subsubsection{主程序流程}
\begin{enumerate}
\item 系统初始化
\item 矩阵按键or蓝牙通信
\item 倒计时模式>实时显示>时间是否一致>判断后是否启动风扇
\item 自动模式>人体红外判断>温度判断>是否启动风扇
\item 手动模式>按键扫描>检验开关>是否启动风扇
\item OLED全程显示状态
\end{enumerate}
\subsection{代码介绍}
我具体负责的部分是按键、电机驱动以及人体红外模块方面的代码

\subsubsection{初始化和配置}
\begin{figure}[h!]
    \centering
    \includegraphics[width=0.5\linewidth]{eb8a0cdbe19687bfdf0f992c8b8bc58b.png}
    \caption{按键初始化}
    \label{fig:enter-label}
\end{figure}
\begin{figure}[h!]
    \centering
    \includegraphics[width=0.5\linewidth]{327392c291af89f317102d8336758cc3.png}
    \caption{电机驱动初始化}
    \label{fig:enter-label}
\end{figure}
\begin{figure}[h!]
    \centering
    \includegraphics[width=0.5\linewidth]{732f5dc2180a02c0dae53e13c1711ba4.png}
    \caption{人体红外初始化}
    \label{fig:enter-label}
\end{figure}
\subsubsection{主功能实现}
\begin{figure}[h!]
    \centering
    \includegraphics[width=0.5\linewidth]{55ec24f7e46fb604729c44b6f1fa8304.png}
    \caption{电机}
    \label{fig:enter-label}
\end{figure}
\begin{figure}[h!]
    \centering
    \includegraphics[width=0.5\linewidth]{d095508ff967796153c3e532dc920257.png}
    \caption{按键}
    \label{fig:enter-label}
\end{figure}
\begin{figure}[h!]
    \centering
    \includegraphics[width=0.75\linewidth]{29f76c589f07212deda8eea386831a4d.png}
    \caption{人体红外}
    \label{fig:enter-label}
\end{figure}
\subsection{技术实现细节}
\subsubsection{OLED屏幕显示系统状态}
由此实时显示各个功能目前具体的参数，帮助用户了解和使用产品。
\begin{itemize}
\item /*模块初始化*/
\item	OLED.Init();		//OLED初始化
\item	Motor.Init();
\item	DHT11.Init();
\item	MatrixKey.Init();
\item	Red.Init();
\item	Timer.Init();
\item	Serial.Init();
\item	BEEP.GPIO.Config();	
\item	OLED.ShowChinese(0,0,"温度");
\item	OLED.ShowChinese(16*4,0,"湿度");	
\item	OLED.ShowChinese(0,16,"模式");
\item	OLED.ShowChinese(16*4,16,"档数");
\item	OLED.ShowNum(16*2,16,Key.M,1,OLED.8X16);
\item	OLED.ShowNum(16*6,16,dang,1,OLED.8X16);	
\item	OLED.ShowChinese(0,16*2,"速度：");
\item	OLED.ShowSignedNum(16*3,16*2,Speed,3,OLED.8X16);	
\item	OLED.ShowChinese(0,16*3,"倒计时：");
\item	OLED.ShowNum(16*4,16*3,Time,2,OLED.8X16);
\item	OLED.Update();	
\item	GPIO.SetBits(GPIOB, GPIO.Pin0);
\item	GPIO.SetBits(GPIOB, GPIO.Pin1);
\item	Delay.ms(100);
\item	GPIO.ResetBits(GPIOB, GPIOPin.0);
\item	GPIO.ResetBits(GPIOB, GPIOPin.1);
\end{itemize}
\subsubsection{设置TIM2定时器的通道3输出PWM信号}
\begin{itemize}
\item void PWM.Init(void)
\item	RCC.APB1PeriphClockCmd(RCC.APB1Periph.TIM2,ENABLE);
\item	RCC.APB2PeriphClockCmd(RCC.APB2Periph.GPIOA, ENABLE);	
\item 作用：开启TIM2定时器和GPIOA端口的时钟，STM32外设需先使能时钟才能配置。
\item	/*GPIO初始化*/
\item	GPIO.InitTypeDef GPIO.InitStructure;
\item	GPIO.InitStructure.GPIO.Mode = GPIO.Mode.AF.PP;
\item	GPIO.InitStructure.GPIO.Pin = GPIO.Pin.2;
\item	GPIO.InitStructure.GPIO.Speed = GPIO.Speed.50MHz;
\item	GPIO.Init(GPIOA, ..GPIO.InitStructure);						
\item 作用：将PA2引脚设置为复用推挽输出模式，用于输出PWM信号（TIM2.CH3通道复用在此引脚）。
\item	TIM.InternalClockConfig(TIM2);
	
\item	TIM.TimeBaseInitTypeDef TIM.TimeBaseInitStructure;
\item	TIM.TimeBaseInitStructure.TIM.ClockDivision = TIM.CKD.DIV1;		
\item TIM.TimeBaseInitStructure.TIM.CounterMode=TIM.CounterMode.Up;		
\item	TIM.TimeBaseInitStructure.TIM.Period = 100 - 1;			
\item	TIM.TimeBaseInitStructure.TIM.Prescaler = 36 - 1;		
\item	TIM.TimeBaseInitStructure.TIM.RepetitionCounter = 0;
\item	TIM.TimeBaseInit(TIM2,..TIM.TimeBaseInitStructure);	
\item	TIM.OCInitTypeDef TIM.OCInitStructure;
\item	TIM.OCStructInit(..TIM.OCInitStructure);		
\item	TIM.OCInitStructure.TIM.OCMode = TIM.OCMode.PWM1;
\item	TIM.OCInitStructure.TIM.OCPolarity = TIM.OCPolarity.High;
\item	TIM.OCInitStructure.TIM.OutputState = TIM.OutputState.Enable;
\item	TIM.OCInitStructure.TIM.Pulse = 0;			
\item	TIM.OC3Init(TIM2,..TIM.OCInitStructure);
\item	TIM.Cmd(TIM2,ENABLE);
\item 作用：配置TIM2的通道3为PWM模式，初始占空比为0%
\item void PWM.SetCompare3(uint16.t compare)
\item	TIM.SetCompare3(TIM2,compare);
\end{itemize}
 PWM频率计算：
 假设系统时钟为72MHz，则：PWN频率=72MHz/（36*100）=20kHz
 占空比分辨率：100级（ARR=99）
\subsubsection{矩阵按键扫描函数}
\begin{itemize}
\item uint8.t Key.GetNum(void)
\item	uint8.t KeyNum = 0;		
\item 消抖逻辑：检测到低电平后延时20ms避开抖动期，确认按键稳定按下
\item	if (GPIO.ReadInputDataBit(GPIOB, GPIO.Pin.10) == 0)			
\item		Delay.ms(20);											
\item		while (GPIO.ReadInputDataBit(GPIOB, GPIO.Pin.10) == 0);	
\item	Delay.ms(20);											
\item		KeyNum = 1;												
\item	if (GPIO.ReadInputDataBit(GPIOB, GPIO.Pin.11) == 0)			
\item		Delay.ms(20);											
\item		while (GPIO.ReadInputDataBit(GPIOB, GPIO.Pin.11) == 0);	
\item		Delay.ms(20);											
\item		KeyNum = 2;												
\item	if (GPIO.ReadInputDataBit(GPIOB, GPIO.Pin.14) == 0)			
\item		Delay.ms(20);											
\item		while (GPIO.ReadInputDataBit(GPIOB, GPIO.Pin.14) == 0);	
\item		Delay.ms(20);											
\item		KeyNum = 3;												
\item	return KeyNum;			
\item 按键一端接地，另一端接GPIO引脚（配置为上拉输入模式，未按下时为高电平，按下时拉低）。
\end{itemize}
\subsubsection{人体红外初始化与状态读取函数}
\begin{itemize}
\item void Red.Init(void)		
\item 	RCC.APB2PeriphClockCmd(RCC.APB2Periph.GPIOA,ENABLE);	
\item 	GPIO.InitTypeDef GPIO.InitStructure;
\item 	GPIO.InitStructure.GPIO.Mode = GPIO.Mode.IPD;
\item 	GPIO.InitStructure.GPIO.Pin = GPIO.Pin.1;
\item 	GPIO.InitStructure.GPIO.Speed = GPIO.Speed.50MHz;
\item 	GPIO.Init(GPIOA,..GPIO.InitStructure);
\item 	下拉输入（IPD）：引脚默认电平为低（0V），当传感器输出高电平时可被检测到。
\item  uint8.t Red.Rdata(void)
\item 	return GPIO.ReadInputDataBit(GPIOA,GPIO.Pin.1);
\item 高电平	检测到目标（如有人）	输出1
\item 低电平	无目标（如无人）       输出0
\end{itemize}